
package com.vladium.utils;

// ----------------------------------------------------------------------------
/**
 * The main interface for exploring an object profile tree. See individual methods
 * for details.
 *  
 * @see ObjectProfiler#profile(Object)
 * 
 * @author (C) <a href="http://www.javaworld.com/columns/jw-qna-index.shtml">Vlad Roubtsov</a>, 2003
 */
public
interface IObjectProfileNode
{
    // public: ................................................................
    
    /**
     * A generic interface for defining node filters. A node filter is used
     * as a guard to determine whether a given visitor should be given a shot
     * as doing something with a profile tree node.
     */
    interface INodeFilter
    {
        /**
         * @param node about to be visited [never null]
         * @return 'true' if 'node' and its children should be visited
         */
        boolean accept (IObjectProfileNode node);
        
    } // end of nested interface

    /**
     * A generic interface for defining node visitors. A node visitor is applied
     * to a profile tree node both before and after visiting the node's children,
     * if any.
     */
    interface INodeVisitor
    {
        /**
         * Pre-order visit.
         * 
         * @param node being visited [never null]
         */
        void previsit (IObjectProfileNode node);
        
        /**
         * Post-order visit.
         * 
         * @param node being visited [never null]
         */
        void postvisit (IObjectProfileNode node);
        
    } // end of nested interface

    
    /**
     * Returns the object associated with this node. This is never null except
     * for shell pseudo-nodes.
     * 
     * @return object instance [null only for shell nodes]
     */
    Object object ();
    
    /**
     * Returns a human-readable name for this node, usually derived from the
     * class field or array index that was used to reach the {@link #object() object}
     * associated with this node.
     * 
     * @return node name [never null]
     */
    String name ();
    
    /**
     * Returns the full size (in bytes) assigned to this node in its profile
     * tree. This is the sum of sizes of the node class's {@link #shell() shell}
     * and its non-primitive non-null {@link #children() instance fields},
     * computed as a closure over the spanning tree produced by {@link ObjectProfiler#profile}. 
     * 
     * @return total node size [always positive]
     */
    int size ();
    /**
     * Returns the reference count for the associated {@link #object()}. This is
     * exactly the number of unique references to this object in the object
     * graph submitted to {@link ObjectProfiler#profile}.
     * 
     * @return reference count [always positive]
     */
    int refcount ();
    
    /**
     * Returns the assigned ownership parent for this node. This is null for the
     * root node.
     * 
     * @return parent node [null only for the root node]
     */
    IObjectProfileNode parent ();
    /**
     * Returns all children of this node. These are non-null references found
     * in this object's class fields (or array slots if the object is of an
     * array type). The result is sorted in decreasing {@link #size() size} order.<P>
     * 
     * Note: the returned array also contains the {@link #shell() shell} pseudo-node.
     *  
     * @return array of children nodes, sorted by size [never null, may be empty]
     */
    IObjectProfileNode [] children ();
    /**
     * Returns the shell pseudo-node for this node. This represents all instance
     * data fields that are "inlined" in the class definition represented by
     * this node (including all superclasses all the way to java.lang.Object).
     * This includes primitive data fields, object references representing
     * non-primitive fields, and (for arrays) the array length field and storage
     * required for the array slots.<P>
     * 
     * Another way to describe this is that node.shell().size() is the minimum
     * size an instance of node.object().getClass() can be (when all non-primitive
     * instance fields are set to 'null').<P>
     * 
     * The returned reference is also guaranteed to be present somewhere in
     * the array returned by {@link #children()}. This data is kept in a
     * separate node instance to simplify tree visiting and node filtering. 
     * 
     * @return shell pseudo-node [null only for shell nodes]
     */
    IObjectProfileNode shell ();
    
    /**
     * Returns the full path from the profile tree root to this node, in that
     * direction. The result includes the root node as well as the current node.<P>
     * 
     * Invariant: node.root() == node.path()[0]
     * Invariant: node.path()[node.path().length - 1] == node
     * Invariant: node.path().length == node.pathlength()
     * 
     * @return node tree path [never null/empty]
     */
    IObjectProfileNode [] path ();
    /**
     * A convenience method for retrieving the root node from any node in a profile
     * tree.<P>
     * 
     * Invariant: node.root() == node iff 'node' is the root of its profile tree
     * Invariant: node.root() == node.path()[0]
     * 
     * @return the root node for the profile tree that the current node is
     * a part of [never null]
     */
    IObjectProfileNode root ();
    /**
     * A convenience method for retrieving this node's tree path length.
     * 
     * @return path length [always positive]
     */
    int pathlength ();
    
    /**
     * A generic hook for traversing profile trees using {@link INodeFilter filters}
     * and {@link INodeVisitor visitors}. See IObjectProfileNode.INodeFilter and
     * IObjectProfileNode.INodeVisitor for more details
     * 
     * @param filter [null is equivalent to no filtering]
     * @param visitor [may not be null]
     * 
     * @return 'true' iff either 'filter' was null or it returned 'true' for this node
     */
    boolean traverse (INodeFilter filter, INodeVisitor visitor);
    
    /**
     * Dumps this node into a flat-text format used by the {@link ObjectProfileVisitors#newDefaultNodePrinter()}
     * default node visitor.
     * 
     * @return indented dump string [could be very large]
     */
    String dump ();

} // end of interface
// ----------------------------------------------------------------------------